<?php

/**
 * @Author: kaihui.wang
 * @Contact  hpuwang@gmail.com
 * @Version: 1.0.0
 * @Date: 2020/3/17 11:24
 */

namespace Eduxplus\CoreBundle\Lib\Service;

class TocService
{

    private static $tree = [];
    private static $id = 0;


    public static function parse($content, $lastResult = '')
    {
        $content = empty($lastResult) ? $content : $lastResult;
        if (stripos($content, '<h1') !== false || stripos($content, '<h2') !== false) {
            // 提取深度自行更改
            $content = preg_replace_callback('/<h([1-6])[^>]*>.*?<\/h\1>/s', 'self::parseCallback', $content);
        }

        return $content;
    }

    /**
     * 解析
     * 
     * @param array $matches 解析值
     * @return string
     */
    public static function parseCallback($matchs)
    {
        $parent = &self::$tree;

        $content = $matchs[0];
        $n = $matchs[1];

        $menu = [
            'num' => $n,
            'title' => trim(strip_tags($content)),
            'unique' => "item_".self::substrs(md5(self::$id . $n . $content), 6, 6, false),
            'sub' => []
        ];

        // 替换原有H标签, 增加前端使用的class, 以及前端使用的一些标签
        $content = str_replace($content, '<h' . $matchs[1] . ' id="' . $menu['unique'] . '" name="' . $menu['unique'] . '" class="doc-heading">' . $menu['title'] . '</h' . $matchs[1] . '>', $content);

        $current = [];

        if ($parent) {
            $current = &$parent[count($parent) - 1];
        }

        // 根
        if (!$parent || (isset($current['num']) && $n <= $current['num'])) {
            $parent[] = $menu;
        } else {
            while (is_array($current['sub'])) {
                // 父子关系
                if ($current['num'] == $n - 1) {
                    $current['sub'][] = $menu;
                    break;
                }
                // 后代关系，并存在子菜单
                elseif ($current['num'] < $n && $current['sub']) {
                    $current = &$current['sub'][count($current['sub']) - 1];
                }
                // 后代关系，不存在子菜单
                else {
                    for ($i = 0; $i < $n - $current['num']; $i++) {

                        $current['sub'][] = [
                            'num' => $current['num'] + 1,
                            'sub' => []
                        ];

                        $current = &$current['sub'][0];
                    }

                    $current['sub'][] = $menu;
                    break;
                }
            }
        }
        self::$id++;
        return $content;
    }


    /**
     * Limit the number of characters in a string.
     *
     * @param  string  $value
     * @param  int     $limit
     * @return string
     */
    public static function limit($value, $limit = 100)
    {
        if (mb_strwidth($value, 'UTF-8') <= $limit) {
            return $value;
        }

        return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8'));
    }

    public static function substrs($str, $start, $length, $suffix = true){
        return substr($str, $start, $length) . ($suffix ? '...' : '');
    }

    /**
     * 标题内特殊符号转为html实体, 以及特殊字符, 修正
     * 
     * @param string $title 待处理字符串
     * @return string
     */
    public static function clearTitle($title = '')
    {
        return str_replace([
            '–',
            '—'

        ], [
            '–',
            '—'
        ], htmlspecialchars($title, ENT_QUOTES));
    }

    /**
     * 构建目录树，生成索引
     * 
     * @param array $tree 结构数组
     * @param bool $isWrap 是否需要套ul
     * @return string
     */
    public static function buildTreeHtml($tree, $num = 1, $isWrap = false)
    {
        $html = '';
        foreach ($tree as $key => $value) {
            if (!isset($value['unique']) && $value['sub']) {
                $html .= self::buildTreeHtml($value['sub'], $value['num']);
            } else {
                $title = self::clearTitle($value['title']);
                $cssOther = $value['num']>1 ? 'ms-3 my-1' : '';
                $li = '<a  class="nav-link '.$cssOther.'" href="#' . $value['unique'] . '" title="' . $title . '">' . $title . '</a>';
                if ($value['sub']) {
                    $li .= self::buildTreeHtml($value['sub'], $value['num'], true);
                }
                $html .= $li;
            }
        }

        if ($isWrap) {
            $html = '<nav class="nav nav-pills flex-column">' . $html . '</nav>';
        }

        return $html;
    }

    /**
     * 获取目录
     * 
     * @param bool $isReturnHtml 是否生成html
     * @return mixed
     */
    public static function get($isReturnHtml = true)
    {
        $tree = self::$tree ?? [];
    
        if($isReturnHtml === true) {
            $tree =  self::buildTreeHtml($tree);
            $tree = '<nav id="navbar-viewer" class="h-100 flex-column align-items-stretch"><nav class="nav nav-pills flex-column">'.$tree.'</nav></nav>';
        }
    
        self::$id = 1;
        self::$tree = [];
    
        return $tree;
    }

}
